home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / fontutil.6 / fontutil / fontutils-0.6 / lib / math.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-27  |  4.1 KB  |  174 lines

  1. /* math.c: define some simple array operations, and other functions.
  2.  
  3. Copyright (C) 1992 Free Software Foundation, Inc.
  4.  
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9.  
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include "config.h"
  20.  
  21.  
  22. /* Numerical errors sometimes make a floating point number just slightly
  23.    larger or smaller than its true value.  When it matters, we need to
  24.    compare with some tolerance, REAL_EPSILON, defined in kbase.h.  */
  25.  
  26. const boolean
  27. epsilon_equal (real v1, real v2)
  28. {
  29.   return
  30.     v1 == v2               /* Usually they'll be exactly equal, anyway.  */
  31.     || fabs (v1 - v2) <= REAL_EPSILON;
  32. }
  33.  
  34.  
  35. /* Return the Euclidean distance between P1 and P2.  */
  36.  
  37. const real
  38. distance (real_coordinate_type p1, real_coordinate_type p2)
  39. {
  40.   return hypot (p1.x - p2.x, p1.y - p2.y);
  41. }
  42.  
  43.  
  44. /* Same thing, for integer points.  */
  45. const real
  46. int_distance (coordinate_type p1, coordinate_type p2)
  47. {
  48.   return hypot ((double) p1.x - p2.x, (double) p1.y - p2.y);
  49. }
  50.  
  51.  
  52. /* Return the arc cosine of V, in degrees in the range zero to 180.  V
  53.    is taken to be in radians.  */
  54.  
  55. const real
  56. acosd (real v)
  57. {
  58.   real a;
  59.  
  60.   if (epsilon_equal (v, 1.0))
  61.     v = 1.0;
  62.   else if (epsilon_equal (v, -1.0))
  63.     v = -1.0;
  64.  
  65.   errno = 0;
  66.   a = acos (v);
  67.   if (errno == ERANGE || errno == EDOM)
  68.     FATAL_PERROR ("acosd");
  69.  
  70.   return a * 180.0 / M_PI;
  71. }
  72.  
  73.  
  74. /* The slope of the line defined by COORD1 and COORD2.  */
  75.  
  76. const real
  77. slope (real_coordinate_type coord1, real_coordinate_type coord2)
  78. {
  79.   assert (coord2.x - coord1.x != 0);
  80.  
  81.   return (coord2.y - coord1.y) / (coord2.x - coord1.x);
  82. }
  83.  
  84.  
  85. /* Turn an integer point into a real one, and vice versa.  */
  86.  
  87. const real_coordinate_type
  88. int_to_real_coord (coordinate_type int_coord)
  89. {
  90.   real_coordinate_type real_coord;
  91.  
  92.   real_coord.x = int_coord.x;
  93.   real_coord.y = int_coord.y;
  94.  
  95.   return real_coord;
  96. }
  97.  
  98.  
  99. const coordinate_type
  100. real_to_int_coord (real_coordinate_type real_coord)
  101. {
  102.   coordinate_type int_coord;
  103.  
  104.   int_coord.x = ROUND (real_coord.x);
  105.   int_coord.y = ROUND (real_coord.y);
  106.  
  107.   return int_coord;
  108. }
  109.  
  110.  
  111. /* See if two points (described by their row and column) are adjacent.  */
  112.  
  113. const boolean
  114. points_adjacent_p (int row1, int col1, int row2, int col2)
  115. {
  116.   int row_diff = abs (row1 - row2);
  117.   int col_diff = abs (col1 - col2);
  118.  
  119.   return
  120.     (row_diff == 1 && col_diff == 1)
  121.     || (row_diff == 0 && col_diff == 1)
  122.     || (row_diff == 1 && col_diff == 0);
  123. }
  124.  
  125.  
  126.  
  127.  
  128. /* Find the largest and smallest elements in an array of reals.  */
  129.  
  130. void
  131. find_bounds (real *values, unsigned value_count, real *min, real *max)
  132. {
  133.   unsigned this_value;
  134.  
  135.   /* We must use FLT_MAX and FLT_MIN, instead of the corresponding
  136.      values for double, because gcc uses the native atof to parse
  137.      floating point constants, and many atof's choke on the extremes.  */
  138.   *min = FLT_MAX;
  139.   *max = FLT_MIN;
  140.  
  141.   for (this_value = 0; this_value < value_count; this_value++)
  142.     {
  143.       if (values[this_value] < *min)
  144.     *min = values[this_value];
  145.  
  146.       if (values[this_value] > *max)
  147.     *max = values[this_value];
  148.     }
  149. }
  150.  
  151.  
  152.  
  153. /* Map a range of numbers, some positive and some negative, into all
  154.    positive, with the greatest being at one and the least at zero.
  155.  
  156.    This allocates new memory.  */
  157.  
  158. real *
  159. map_to_unit (real *values, unsigned value_count)
  160. {
  161.   real smallest, largest;
  162.   int this_value;
  163.   real *mapped_values = xmalloc (sizeof (real) * value_count);
  164.  
  165.   find_bounds (values, value_count, &smallest, &largest);
  166.  
  167.   largest -= smallest;        /* We never care about largest itself. */
  168.  
  169.   for (this_value = 0; this_value < value_count; this_value++)
  170.     mapped_values[this_value] = (values[this_value] - smallest) / largest;
  171.  
  172.   return mapped_values;
  173. }
  174.